package com.borya.util;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URL;
import java.util.Date;
import java.util.List;

import com.borya.framework.util.ObjectUtils;
import org.apache.log4j.Logger;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.DeleteObjectsRequest;
import com.aliyun.oss.model.DeleteObjectsResult;

/**
 * 阿里云OSS文件操作
 * 
 * @author Administrator
 *
 */
public class AliOSSUtil {

	private static Logger log = Logger.getLogger(AliOSSUtil.class);

	private final static String endpointFormat = "https://%soss-cn-hangzhou.aliyuncs.com";
	private final static String accessKeyId = "0RQkxi620oJSugUM";
	private final static String accessKeySecret = "1O6VYhgA8XJKgoxy96v4YbVFAQRTpQ";

	// private static final String downoadUrl =
	// "https://yuantelapk.oss-cn-hangzhou.aliyuncs.com";
	public final static String rootBacketName = Constant.ROOT_BACKET_NAME;//SystemConfig.getInstance().getProperty("oss.backetName");//"datayuantel"

	private AliOSSUtil(){}
	
	public static class UploadResult{
		private boolean flag = false;
		private String netUrl = "";
		
		public UploadResult(boolean flag){
			this.flag = flag;
		}
		public boolean isFlag() {
			return flag;
		}
		public void setFlag(boolean flag) {
			this.flag = flag;
		}
		public String getNetUrl() {
			return netUrl;
		}
		public void setNetUrl(String netUrl) {
			this.netUrl = netUrl;
		}
		public String toString() {
			return "[flag=" + flag + ", netUrl=" + netUrl + "]";
		}
	}
	
	public static OSS getOSSClient() {
		String endpoint = String.format(endpointFormat, "");
		return new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
	}

	public static String getDownloadUrl(String fileName) {
		return getDownloadUrl(rootBacketName, fileName);
	}
	public static String getDownloadUrl(String bucketName, String fileName) {
		return String.format(endpointFormat, bucketName + ".") + "/" + fileName;
	}

	public static boolean create(final String dir) {
		return create(rootBacketName, dir);
	}

	private static boolean isExistBacketName(OSS client, String backetName) {
		return client.doesBucketExist(backetName);
	}

	/**
	 * 创建文件夹 eg: MyObjectKey/ final String keySuffixWithSlash = "MyObjectKey/";
	 * 
	 * @param dir
	 */
	public static boolean create(final String backetName, final String dir) {
		OSS client = getOSSClient();
		if (!isExistBacketName(client, backetName))
			return false;
		try {
			client.putObject(backetName, dir, new ByteArrayInputStream(new byte[0]));
			log.error("Creating an empty folder " + dir + "\n");

			/*
			 * Verify whether the size of the empty folder is zero
			 */
			// OSSObject object = client.getObject(bucketName, dir);
			// log.error("Size of the empty folder '" + object.getKey() + "' is
			// " +
			// object.getObjectMetadata().getContentLength());
			// log.error(object);
			// object.getObjectContent().close();
			return true;
		} catch (OSSException oe) {
			log.error("Caught an OSSException, which means your request made it to OSS, " + "but was rejected with an error response for some reason.");
			log.error("Error Message: " + oe.getErrorCode());
			log.error("Error Code:       " + oe.getErrorCode());
			log.error("Request ID:      " + oe.getRequestId());
			log.error("Host ID:           " + oe.getHostId());
		} catch (Exception ce) {
			log.error("Caught an ClientException, which means the client encountered " + "a serious internal problem while trying to communicate with OSS, " + "such as not being able to access the network.");
			log.error("Error Message: " + ce.getMessage());
		} finally {
			/*
			 * Do not forget to shut down the client finally to release all
			 * allocated resources.
			 */
			client.shutdown();
		}
		return false;
	}
	public static boolean delete(List<String> filePaths) {
		return delete(rootBacketName, filePaths);
	}
	public static boolean delete(final String bucketName, List<String> filePaths) {
		try {
			// 创建OSSClient实例。
			OSS ossClient = getOSSClient();
			if (!isExistBacketName(ossClient, bucketName))
				return false;
			DeleteObjectsResult deleteObjectsResult = ossClient.deleteObjects(new DeleteObjectsRequest(bucketName).withKeys(filePaths));
			List<String> deletedObjects = deleteObjectsResult.getDeletedObjects();
			log.info("删除的文件:" + deletedObjects);
			// 关闭OSSClient。
			ossClient.shutdown();
			return true;
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			return false;
		}
	}
	
	public static boolean delete(String filePath) {
		return delete(rootBacketName, filePath);
	}
	
	public static boolean delete(final String bucketName, String filePath) {

		try {
			// 创建OSSClient实例。
			OSS ossClient = getOSSClient();
			if (!isExistBacketName(ossClient, bucketName))
				return false;
			ossClient.deleteObject(bucketName, filePath);
			// List<String> deletedObjects =
			// deleteObjectsResult.getDeletedObjects();
			// 关闭OSSClient。
			ossClient.shutdown();
			return true;
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			return false;
		}
	}

	/**
	 * 上传网络流
	 * 
	 * @param url
	 *            new URL("https://www.aliyun.com/")
	 * @param filePathAndFileName
	 *            文件的路径+文件名称
	 * 
	 */
	public static UploadResult upload(String bucketName, URL url, String filePathAndFileName) {
		try {
			return upload(bucketName, url.openStream(), filePathAndFileName);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			return new UploadResult(false);
		}
	}

	public static UploadResult upload(URL url, String filePathAndFileName) {
		return upload(rootBacketName,url,filePathAndFileName);
	}
	
	/**
	 * 上传本地文件
	 * 
	 * @param localFilePath
	 * @param filePathAndFileName
	 * @return
	 */
	public static UploadResult upload(String bucketName, String localFilePath, String filePathAndFileName) {
		try {
			return upload(bucketName, new FileInputStream(localFilePath), filePathAndFileName);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			return new UploadResult(false);
		}
	}

	public static UploadResult upload(String localFilePath, String filePathAndFileName) {
		return upload(rootBacketName, localFilePath, filePathAndFileName);
	}
	
	/**
	 * 上传文件流
	 * 
	 * @param inputStream
	 * @param filePathAndFileName
	 * @return
	 */
	public static UploadResult upload(String bucketName, InputStream inputStream, String filePathAndFileName) {
		UploadResult result = new UploadResult(false);
		if (filePathAndFileName == null || filePathAndFileName.trim().length() == 0) {
			return result;
		}
		filePathAndFileName = new File(filePathAndFileName).getPath().trim();
		if(filePathAndFileName.trim().startsWith(File.separator)){
			filePathAndFileName=filePathAndFileName.substring(1);
		}
		try {
			// 创建OSSClient实例。
			OSS ossClient = getOSSClient();
			if (!isExistBacketName(ossClient, bucketName))
				return result;
			// 上传文件流。
			ossClient.putObject(bucketName, getkey(filePathAndFileName), inputStream);
			// 关闭OSSClient。
			ossClient.shutdown();
			result.setFlag(true);
			result.setNetUrl(getDownloadUrl(rootBacketName, filePathAndFileName));

			return result;
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			return result;
		}
	}

	public static UploadResult upload(InputStream inputStream, String filePathAndFileName) {
		return upload(rootBacketName, inputStream, filePathAndFileName);
	}
	/**
	 * 上传本地文件：
	 * 
	 * @param localFile
	 *            本地文件 new File("d:/img/22.jpg")
	 * @param filePathAndFileName
	 *            文件的路径+文件名称 "MyObjectKey/22.jpg"
	 */
	public static UploadResult upload(String bucketName, File localFile, String filePathAndFileName) {
		try {
			return upload(bucketName, new FileInputStream(localFile), filePathAndFileName);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			return new UploadResult(false);
		}
	}

	public static UploadResult upload(File localFile, String filePathAndFileName) {
		return upload(rootBacketName, localFile, filePathAndFileName);
	}
	
	public static boolean doseObjectExist(String filePathAndFileName){
		// 创建OSSClient实例。
		OSS ossClient = getOSSClient();
		// 判断文件是否存在。doesObjectExist还有一个参数isOnlyInOSS，如果为true则忽略302重定向或镜像；如果
//		为false，则考虑302重定向或镜像。
		boolean found = ossClient.doesObjectExist(rootBacketName, getkey(filePathAndFileName));
		// 关闭OSSClient。
		ossClient.shutdown();
		return found;
	}
	public static String getkey(String key){
		key = new File(key).getPath().trim();
		if(key.startsWith("http"))
			key = key.substring(key.lastIndexOf("com/")+4);
		while(key.startsWith("/"))
			key = key.substring(1);
		return key;
	}


	public static String generatePresignedUrl(final String objectName){
		return generatePresignedUrl(120,objectName);
	}

	public static String generatePresignedUrl(long expireSeconds,final String objectName){
		if(ObjectUtils.isNullOrEmpty(objectName)
				|| !objectName.contains("aliyuncs.com"))
			return objectName;
		return generatePresignedUrl(getBucketName(objectName),expireSeconds,objectName);
	}

	private static String getBucketName(String ossUrl){
		if(ossUrl.contains("//") && ossUrl.contains(".oss"))
			return ossUrl.substring(ossUrl.indexOf("//")+2,ossUrl.indexOf(".oss"));
		return ossUrl;
	}


	public static String generatePresignedUrl(String bucketName,long expireSeconds,final String objectName){
		// Endpoint以杭州为例，其它Region请按实际情况填写。
//		String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
//		// 阿里云主账号AccessKey拥有所有API的访问权限，风险很高。
		//强烈建议您创建并使用RAM账号进行API访问或日常运维，请登录 https://ram.console.aliyun.com 创建RAM账号。
//		String accessKeyId = "<yourAccessKeyId>";
//		String accessKeySecret = "<yourAccessKeySecret>";
//		String bucketName = "<yourBucketName>";
//		String objectName = "<yourObjectName>";

		// objectName不能以/开头
		String objName = objectName;
		if(objectName.startsWith(String.format(endpointFormat, bucketName+"."))){
			objName = objectName.substring(String.format(endpointFormat, bucketName+".").length()+1);
		}
		if(objName.startsWith("/")){
			objName = objName.substring(1);
		}
		// 创建OSSClient实例。
		OSS ossClient = getOSSClient();
		// 设置URL过期时间为1小时。
		Date expiration = new Date(new Date().getTime() + expireSeconds * 1000);
		// 生成以GET方法访问的签名URL，访客可以直接通过浏览器访问相关内容。
		URL url = ossClient.generatePresignedUrl(bucketName, objName, expiration);

		// 关闭OSSClient。
		ossClient.shutdown();
		return url.toString();
	}

//	public static void main(String[] args) {
//		String testBacketName = "test4borya";
//		UploadResult upload = AliOSSUtil.upload(testBacketName,"D:/test_oss.png","test/test_wxl2.png");
//		System.out.println(upload);
//		boolean doseObjectExist = doseObjectExist("test/test_wxl2.png");
//		System.out.println(doseObjectExist);
//		System.out.println("aaa///ddd.jpg".trim());
//	}

}